package com.study.spmongodb.book.wwj.char25;


import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * @author MI
 * @version 1.0
 * @date 2020/11/30 22:38
 */
public class LRUCache<K, V> {


    /**
     * 用于存放 key的顺序
     */
    private final LinkedList<K> keyList = new LinkedList<>();

    // 用于存放数据
    private final Map<K, V> cache = new HashMap<>();
    /**
     * cache的最大容量
     */
    private final int capacity;

    //cacheLoader 接口提供了一种加载数据的方式
    private final CacheLoader<K, V> cacheLoader;

    public LRUCache(int capacity, CacheLoader<K, V> cacheLoader) {
        this.capacity = capacity;
        this.cacheLoader = cacheLoader;
    }

    public void put(K key, V value) {
        //当元素超过容量时，将最老的数据清除
        if (keyList.size() >= capacity) {
            final K eldestKsy = keyList.removeFirst();
            cache.remove(eldestKsy);
        }
        //如果数据已经存在，则从key的队列中删除
        if (keyList.contains(key)) {
            keyList.remove(key);
        }
        //将 key存放至 队尾
        keyList.addLast(key);
        cache.put(key, value);
    }

    public V get(K key) throws Exception {

        V value;
        //先将key  从key list中删除
        final boolean remove = keyList.remove(key);
        if (!remove) {
            //表示删除数据不存在
            value = cacheLoader.load(key);
            this.put(key, value);
        } else {
            //数据存在，则从cache中返回数据，并且将可以再次放入队尾
            value = cache.get(key);
            keyList.addLast(key);
        }
        return value;
    }

    @Override
    public String toString() {
        return this.keyList.toString();
    }


    public static void main(String[] args) throws Exception {
        final LRUCache<Object, Object> cache = new LRUCache<>(5, key -> new Reference());


        cache.get("Alex");
        cache.get("Jack");
        cache.get("Gavin");
        cache.get("Dillon");
        cache.get("Leo");

        cache.get("Jenny");
        System.out.println(cache.toString());


    }
}
